package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.remark.LikedTimesDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionAdminPageQuery;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.dto.ReplyPageQuery;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.common.constants.MqConstants.Exchange.LEARNING_EXCHANGE;
import static com.tianji.common.constants.MqConstants.Key.WRITE_REPLY;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author WFan
 * @since 2025-03-27
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final InteractionQuestionMapper questionMapper;
    private final UserClient userClient;
    private final RemarkClient remarkClient;
    private final RabbitMqHelper mqHelper;

    /**
     * 新增回答或评论
     *
     * @param replyDTO
     */
    @Override
    @Transactional
    public void saveReply(ReplyDTO replyDTO) {
        if (ObjectUtil.isEmpty(replyDTO)) {
            throw new IllegalArgumentException("参数不能为空");
        }


        // 1.保存回答或评论
        InteractionReply reply = BeanUtil.toBean(replyDTO, InteractionReply.class);
        reply.setUserId(UserContext.getUser());
        this.save(reply);

        InteractionQuestion question = questionMapper.selectById(replyDTO.getQuestionId());
        if (ObjectUtil.isEmpty(question)) {
            throw new IllegalArgumentException("问题不存在");
        }

        // 2.判断是否是回答
        if (ObjectUtil.isNotEmpty(replyDTO.getAnswerId())) {
            // 2.1 是评论，更新回答评论数量
            this.lambdaUpdate()
                    .eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .setSql("reply_times = reply_times + 1")
                    .update();
        } else {
            // 2.2 是回答，更新问题回答数量、最近一次的回答id
            LambdaUpdateWrapper<InteractionQuestion> wrapper = Wrappers.<InteractionQuestion>lambdaUpdate().eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .setSql("answer_times = answer_times + 1")
                    .set(InteractionQuestion::getLatestAnswerId, reply.getId());
            questionMapper.update(null, wrapper);
        }

        // 3.判断是否是学生提交
        if (replyDTO.getIsStudent()) {
            // 3.1 是学生提交，更新问题状态为未查看
            question.setStatus(0);
            questionMapper.updateById(question);
            // 4.发送新增积分消息
            try {
                mqHelper.send(LEARNING_EXCHANGE,WRITE_REPLY, UserContext.getUser());
            } catch (Exception e) {
                log.error("新增积分消息发送失败", e);
            }
        }
    }

    /**
     * 分页查询互动回答或评论列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> queryReplyPageList(ReplyPageQuery query) {
        Boolean noHidden = true;
        return getAnswerOrReplyVOPage(query, noHidden);
    }

    /**
     * 分页查询互动回答或评论列表
     *
     * @param query
     * @param noHidden 是否包含隐藏回答或评论
     * @return
     */
    private PageDTO<ReplyVO> getAnswerOrReplyVOPage(ReplyPageQuery query, Boolean noHidden) {
        // 1.分页查询出回答或评论列表
        Page<InteractionReply> page = null;
        if (ObjectUtil.isEmpty(query.getAnswerId())) {
            // 根据问题id查询回答
            page = this.lambdaQuery().eq(InteractionReply::getQuestionId, query.getQuestionId())
                    .eq(noHidden, InteractionReply::getHidden, false)
                    .eq(InteractionReply::getAnswerId, 0)
                    .page(query.toMpPageDefaultSortByCreateTimeDesc());
        } else {
            // 根据answerId查询评论
            page = this.lambdaQuery().eq(InteractionReply::getAnswerId, query.getAnswerId())
                    .eq(noHidden, InteractionReply::getHidden, false)
                    .page(query.toMpPageDefaultSortByCreateTimeDesc());

        }

        List<InteractionReply> records = page.getRecords();

        // 2.列表查询没有数据返回空集合
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        // 3.获取用户id集合
        Set<Long> userIds = new HashSet<>(records.size());
        List<Long> targetReplyIds = new ArrayList<>(records.size());
        Set<Long> replyIds = new HashSet<>(records.size());
        for (InteractionReply record : records) {
            if (noHidden) {
                if (!record.getAnonymity()) {
                    userIds.add(record.getUserId());
                }
            } else {
                userIds.add(record.getUserId());
            }
            // 如果是评论，需要获取被评论的对象id、需要获取回复的目标id
            if (ObjectUtil.isNotEmpty(record.getTargetUserId())) {
                // 获取被评论对象id
                userIds.add(record.getTargetUserId());
                // 获取回复的目标id
                targetReplyIds.add(record.getTargetReplyId());
            }
            replyIds.add(record.getId());
        }

        // 4.根据用户id查询用户信息
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> usersMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));

        // 获取点赞的回复或回答id集合
        Set<Long> likeIds = remarkClient.listLikedStatus(replyIds);

        // 5.如果是评论，需要获取被评论对象是否匿名
        Map<Long, Boolean> anonymityMap = new HashMap<>(records.size());
        if (ObjectUtil.isNotEmpty(query.getAnswerId())) {
            anonymityMap = this.lambdaQuery().in(InteractionReply::getId, targetReplyIds).list().stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getAnonymity));
        }

        // 6.封装vo
        List<ReplyVO> vos = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            ReplyVO vo = BeanUtil.toBean(record, ReplyVO.class);
            if (noHidden) {
                if (!record.getAnonymity()) {
                    vo.setUserName(usersMap.get(record.getUserId()).getName());
                    vo.setUserIcon(usersMap.get(record.getUserId()).getIcon());
                }
            } else {
                vo.setUserName(usersMap.get(record.getUserId()).getName());
                vo.setUserIcon(usersMap.get(record.getUserId()).getIcon());
            }
            // 如果是评论，需要填充被评论的对象昵称
            if (ObjectUtil.isNotEmpty(query.getAnswerId())) {
                if (noHidden) {
                    // 不匿名就填充被评论对象昵称
                    if (ObjectUtil.isNotEmpty(record.getTargetReplyId()) && !anonymityMap.get(record.getTargetReplyId())) {
                        vo.setTargetUserName(usersMap.get(record.getTargetUserId()).getName());
                    }
                } else {
                    if (ObjectUtil.isNotEmpty(record.getTargetReplyId())) {
                        vo.setTargetUserName(usersMap.get(record.getTargetUserId()).getName());
                    }
                }
            }
            vo.setLiked(likeIds.contains(record.getId()));
            vos.add(vo);
        }
        return PageDTO.of(page, vos);
    }

    /**
     * 管理端分页查询回答或评论
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> queryAnswerPage(ReplyPageQuery query) {
        Boolean noHidden = false;
        return getAnswerOrReplyVOPage(query, noHidden);
    }

    /**
     * 显示或隐藏评论
     *
     * @param id
     * @param hidden
     */
    @Override
    public void updateHidden(Long id, Boolean hidden) {

        this.lambdaUpdate().eq(InteractionReply::getId, id)
                .set(InteractionReply::getHidden, hidden)
                .update();

        this.lambdaUpdate().eq(InteractionReply::getAnswerId,id)
                .set(InteractionReply::getHidden, hidden)
                .update();

    }

    /**
     * 更新点赞次数
     *
     * @param likedTimesMsg
     */
    @Override
    public void updateLikedTimes(List<LikedTimesDTO> likedTimesMsg) {
        // 消息健壮性判断
        if (ObjectUtil.isEmpty(likedTimesMsg)){
            log.error("点赞次数变更消息格式异常，消息:{}", likedTimesMsg);
            return;
        }

        List<InteractionReply> replies = new ArrayList<>(likedTimesMsg.size());
        for (LikedTimesDTO likedTimesDTO : likedTimesMsg) {
            InteractionReply reply = new InteractionReply();
            reply.setLikedTimes(likedTimesDTO.getLikedTimes());
            reply.setId(likedTimesDTO.getBizId());
            replies.add(reply);
        }
        this.updateBatchById(replies);

    }


}
